package com.mxx.common.netty.ws;

import com.mxx.common.netty.NettyWebsocketOperator;
import io.netty.channel.*;
import io.netty.handler.codec.http.websocketx.*;
import lombok.extern.slf4j.Slf4j;

/**
 * @Auther: Mr. Zeng
 * @Date: 2020/6/29 17:03
 * @Description: 暂无描述
 */
@Slf4j
@ChannelHandler.Sharable
public class NettyWebsocketHandler extends ChannelInboundHandlerAdapter {

    /**
     * 序列化转换
     */
    private NettyWebsocketOperator nettyWebsocketOperator;


    public NettyWebsocketHandler(NettyWebsocketOperator nettyWebsocketOperator) {
        this.nettyWebsocketOperator = nettyWebsocketOperator;
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//        SocketChannel channel = (SocketChannel) ctx.channel();
//        InetSocketAddress localAddress = channel.localAddress();
//        log.info("连接已下线 -> [{}:{}], ", localAddress.getHostString(), localAddress.getPort());
        nettyWebsocketOperator.close(ctx);

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        if (msg instanceof WebSocketFrame) {
            WebSocketFrame webSocketFrame = (WebSocketFrame) msg;
            //关闭请求
            if (webSocketFrame instanceof CloseWebSocketFrame) {
                Channel channel = ctx.channel();
                channel.writeAndFlush(webSocketFrame.retain(), channel.newPromise()).addListener(ChannelFutureListener.CLOSE);
                return;
            }
            //ping请求
            if (webSocketFrame instanceof PingWebSocketFrame) {
                ctx.channel().write(new PongWebSocketFrame(webSocketFrame.content().retain()));
                return;
            }

            //只支持文本格式，不支持二进制消息
            if (!(webSocketFrame instanceof TextWebSocketFrame)) {
                throw new Exception("仅支持文本格式");
            }
            nettyWebsocketOperator.execute(ctx, webSocketFrame);
        } else {
            ctx.fireChannelRead(msg);
        }

    }


    /**
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        nettyWebsocketOperator.canException(ctx, cause);
    }


}
